package com.wn.icloud.provider.uac.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wn.icloud.biz.BaseBiz;
import com.wn.icloud.common.msg.ObjectRestCode;
import com.wn.icloud.common.msg.ObjectRestResponse;
import com.wn.icloud.common.msg.TableResultResponse;
import com.wn.icloud.common.utils.UUIDUtil;
import com.wn.icloud.common.vo.user.BaseEnterpriseInfo;
import com.wn.icloud.common.vo.user.UserInfo;
import com.wn.icloud.provider.uac.remote.constant.UserRedisKeyConstant;
import com.wn.icloud.provider.uac.constant.UserTypeConstant;
import com.wn.icloud.provider.uac.entity.EnterpriseInfo;
import com.wn.icloud.provider.uac.entity.User;
import com.wn.icloud.provider.uac.mapper.EnterpriseInfoDao;
import com.wn.icloud.provider.uac.mapper.LinkUserEnterpriseDao;
import com.wn.icloud.provider.uac.mapper.MenuMapper;
import com.wn.icloud.provider.uac.mapper.UserMapper;
import com.wn.icloud.provider.uac.remote.vo.LoginReqVO;
import com.wn.icloud.provider.uac.remote.vo.ResetUserPassWordReqVO;
import com.wn.icloud.provider.uac.service.dto.PasswordResetDTO;
import com.wn.icloud.provider.uac.service.impl.SendSmsServiceImpl;
import com.wn.icloud.provider.uac.vo.RegisterReqVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Rainer
 * @create 2017-06-08 16:23
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserBiz extends BaseBiz<UserMapper, User> {

    @Autowired
    private MenuMapper menuMapper;

    @Autowired
    private EnterpriseInfoDao enterpriseInfoDao;

    @Autowired
    private LinkUserEnterpriseDao linkUserEnterpriseDao;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();

    @Override
    public void insertSelective(User entity) {
//        String password = encoder.encode(entity.getPassword());
//        entity.setPassword(password);
//        super.insertSelective(entity);
    }

    @Override
//    @CacheClear(pre="user{1.username}")
    public void updateSelectiveById(User entity) {
        super.updateSelectiveById(entity);
    }

    /**
     * 根据用户名获取用户信息
     *
     * @param username
     * @return
     */
//    @Cache(key="user{1}")
    public User getUserByUsername(String username) {
        User user = new User();
        user.setUsername(username);
        return mapper.selectOne(user);
    }

    public void resetPassword(PasswordResetDTO passwordResetDTO) {
        User user = this.selectById(passwordResetDTO.getUserId());
        Assert.notNull(user, String.format("User not exits:[]", passwordResetDTO.getUserId()));
        String password = encoder.encode(passwordResetDTO.getNewPassword());
        user.setPassword(password);
        this.updateSelectiveById(user);
    }

    public void updatePassword(PasswordResetDTO passwordResetDTO) {
        User user = this.selectById(passwordResetDTO.getUserId());
        Assert.notNull(user, String.format("User not exits:[]", passwordResetDTO.getUserId()));
        // 检测密码
        Assert.isTrue(encoder.matches(passwordResetDTO.getOldPassword(), user.getPassword()), "旧密码错误");
        String password = encoder.encode(passwordResetDTO.getNewPassword());
        user.setPassword(password);
        this.updateSelectiveById(user);
    }


    public TableResultResponse getUserlist(Integer page, Integer size) {
        Example example = new Example(User.class);
        Page<Object> result = PageHelper.startPage(page, size);
        List<User> users = mapper.selectByExample(example);
        List<UserInfo> userInfos = new ArrayList<>();
        users.forEach(user -> {
            UserInfo userInfo = new UserInfo();
            userInfo.setId(user.getId() + "");
            userInfo.setName(user.getName());
            userInfo.setDescription(user.getDescription());
            userInfo.setUsername(user.getUsername());
            userInfo.setSex(user.getSex());
            userInfo.setTelPhone(user.getTelPhone());
            userInfo.setMobilePhone(user.getMobilePhone());
            userInfos.add(userInfo);
        });
        return new TableResultResponse<UserInfo>(result.getTotal(), userInfos);
    }

    public UserInfo getUserInfo(String userid) {
        User user = new User();
        user.setId(userid);
        User user1 = mapper.selectOne(user);
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user1.getId() + "");
        userInfo.setName(user1.getName());
        userInfo.setDescription(user1.getDescription());
        userInfo.setUsername(user1.getUsername());
        return userInfo;
    }


    /**
     * 注册
     *
     * @param registerReqVO
     */
    public ObjectRestResponse register(RegisterReqVO registerReqVO) {
        int phoneOrExist = mapper.queryExsitPhone(registerReqVO.getPhoneNum());
        if (phoneOrExist != 0) {
            return ObjectRestResponse.failure(ObjectRestCode.REGISTER_FAILURE, null);// 用户已注册
        }
        //获取真实验证码
        String realMsgCode = redisTemplate.opsForValue().get(UserRedisKeyConstant.REGISTER + registerReqVO.getPhoneNum()).toString();
        if (!registerReqVO.getMsgCode().equals(realMsgCode)) {
            return ObjectRestResponse.failure(ObjectRestCode.SMS_ERROR,null );// 验证码错误
        }
        String password = encoder.encode(registerReqVO.getPassword());
        User user = new User();
        user.setId(UUIDUtil.getUUID());
        user.setPassword(password);
        user.setMobilePhone(registerReqVO.getPhoneNum());
        user.setType(UserTypeConstant.app);
        user.setCertEnterprise(0);
        user.setName("QYB-" + SendSmsServiceImpl.sixCode());
        user.setUsername("QYB-" + SendSmsServiceImpl.sixCode());
        mapper.insert(user);
        user.setPassword("");
        return ObjectRestResponse.success().data(user);
    }


    public UserInfo login(LoginReqVO loginReqVO) {
        User user = mapper.queryByPhone(loginReqVO.getMobilePhone());
        UserInfo info = new UserInfo();
        if (user == null){
            return info;
        }
        if (encoder.matches(loginReqVO.getPassword(), user.getPassword())) {
            BeanUtils.copyProperties(user, info);
            info.setId(user.getId().toString());
        }
        return info;
    }

    public UserInfo loginPhone(LoginReqVO loginReqVO) {
        Object realCode = redisTemplate.opsForValue().get(UserRedisKeyConstant.LOGIN + loginReqVO.getMobilePhone());
        UserInfo info = new UserInfo();
        if (realCode == null){
            return info;
        }
        if (!loginReqVO.getCode().equals(realCode.toString())){
            return info;
        }
        User user = mapper.queryByPhone(loginReqVO.getMobilePhone());
            BeanUtils.copyProperties(user, info);
            info.setId(user.getId().toString());
        return info;
    }

    public ObjectRestResponse getUserInfoEnterprise(String userId){
        User user = new User();
        user.setId(userId);
        User user1 = mapper.selectOne(user);
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user1.getId());
        userInfo.setName(user1.getName());
        userInfo.setDescription(user1.getDescription());
        userInfo.setUsername(user1.getUsername());
        userInfo.setCertEnterprise(user1.getCertEnterprise());
        List<String> enterpriseIdList = linkUserEnterpriseDao.queryById(user1.getId());
        if (CollectionUtils.isEmpty(enterpriseIdList)){
            userInfo.setBaseEnterpriseInfos(null);
        }else {
            List<EnterpriseInfo> enterpriseInfos = enterpriseInfoDao.queryByIdList(enterpriseIdList);
            List<BaseEnterpriseInfo> baseEnterpriseInfos = new ArrayList<>();
            for (EnterpriseInfo e1 : enterpriseInfos){
                BaseEnterpriseInfo baseEnterpriseInfo = new BaseEnterpriseInfo();
                BeanUtils.copyProperties(e1, baseEnterpriseInfo);
                baseEnterpriseInfos.add(baseEnterpriseInfo);
            }
            userInfo.setBaseEnterpriseInfos(baseEnterpriseInfos);
        }
        return ObjectRestResponse.success(userInfo);
    }

   public ObjectRestResponse resetUserPassWord(ResetUserPassWordReqVO resetUserPassWordReqVO){


       String redisKey = UserRedisKeyConstant.PASSWORD_RESET_KEY + resetUserPassWordReqVO.getPhone();
       Object resetPasswordecret = redisTemplate.opsForValue().get(redisKey);
       if (resetPasswordecret == null){
            return ObjectRestResponse.failure(ObjectRestCode.FAILURE);
       }else {
           String resetPasswordecretStr = resetPasswordecret.toString();
           if (StringUtils.isEmpty(resetPasswordecretStr)){
               return ObjectRestResponse.failure(ObjectRestCode.FAILURE);
           }
           if (!resetPasswordecretStr.equals(resetUserPassWordReqVO.getUid())){
               return ObjectRestResponse.failure(ObjectRestCode.FAILURE);
           }
           User user = new User();
           user.setMobilePhone(resetUserPassWordReqVO.getPhone());
           user.setPassword(encoder.encode(resetUserPassWordReqVO.getNewPassWord()));
           mapper.updatePassWord(user);
           redisTemplate.delete(UserRedisKeyConstant.PASSWORD_RESET_KEY + resetUserPassWordReqVO.getPhone());
           return ObjectRestResponse.success();
       }
    }

    public ObjectRestResponse updateUserPassword(ResetUserPassWordReqVO resetUserPassWordReqVO,String userid){
        User user = mapper.queryById(userid);
        if (encoder.matches(user.getPassword(),resetUserPassWordReqVO.getOldPassword())){
            user = new User();
            user.setId(userid);
            user.setPassword(encoder.encode(resetUserPassWordReqVO.getNewPassWord()));
            mapper.update(user);
            return ObjectRestResponse.success();
        }else {
            //TODO 限频率
            return ObjectRestResponse.failure(ObjectRestCode.USER_OLD_PASSWORD);
        }
    }
}
